import os
import cv2
import base64
import time
import json
from openai import OpenAI

def make_emergency_call(message, callback_fn=None):
    print("=" *50)
    print(f"！！！紧急呼叫！！！ Reason: {message}")
    print("=" *50)
    
    # 获取CameraDetector实例的引用
    detector = getattr(make_emergency_call, 'detector', None)
    if detector:
        current_time = time.time()
        # 检查是否在超时时间内
        if current_time - detector.last_emergency_time <= detector.emergency_timeout:
            detector.emergency_count += 1
            print(f"紧急情况计数：{detector.emergency_count}/3")
        else:
            detector.emergency_count = 1  # 重新开始计数
            print("重新开始计数：1/3")
        
        detector.last_emergency_time = current_time
        
        # 如果达到3次，触发特殊回调并拨打电话
        if detector.emergency_count >= 3 and callback_fn:
            emergency_message = f"紧急情况！连续{detector.emergency_count}次检测到异常：{message}。正在拨打儿子电话寻求帮助。"
            print(emergency_message)
            callback_fn("make_call", {"phone_number": "13243784433"})  # 这里需要替换为实际的电话号码
            detector.emergency_count = 0  # 重置计数
        elif callback_fn:
            callback_fn("normal", f"摄像头发现主人遇到了情况:{message}，请先表示关心一下我，再问我需要帮助吗？")
    else:
        if callback_fn:
            callback_fn("normal", f"摄像头发现主人遇到了情况:{message}，请先表示关心一下我，再问我需要帮助吗？")

class CameraDetector:
    def __init__(self, emergency_callback=None):
        self.client = OpenAI(
            api_key="sk-19d6508c55d640e6b954db2483ad727c",
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
        )
        self.camera = None
        self.running = True
        self.last_api_call = 0
        self.api_interval = 2
        self.emergency_callback = emergency_callback
        
        # 添加紧急呼叫计数器
        self.emergency_count = 0
        self.last_emergency_time = 0
        self.emergency_timeout = 60  # 30秒内的连续触发才计数
        
        # 定义工具
        self.tools = [
            {
                "type": "function",
                "function": {
                    "name": "make_emergency_call",
                    "description": "这是一个强制性的工具调用。当且仅当检测到以下情况时，必须通过工具调用来执行此函数（不要只在文本中提到）：1. 人不是完全站立；2. 人不是正确坐在椅子上。任何其他姿势都必须触发此函数调用。此函数用于发出紧急呼叫。",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "message": {
                                "type": "string",
                                "description": "简要描述检测到的异常姿势，例如：'人员倒地'，'人员蹲下'等。不要包含任何主观判断。"
                            }
                        },
                        "required": ["message"]
                    }
                }
            }
        ]

    def capture_and_analyze(self):
        # 设置detector引用，以便make_emergency_call函数可以访问
        make_emergency_call.detector = self
        try:
            if not self.camera:
                self.camera = cv2.VideoCapture(0)
            
            while self.running:
                try:
                    ret, frame = self.camera.read()
                    if not ret:
                        print("Failed to capture frame")
                        time.sleep(1)  # 添加延迟，避免快速循环
                        continue
                    
                    current_time = time.time()
                    if current_time - self.last_api_call < self.api_interval:
                        continue
                    
                    self.last_api_call = current_time
                    
                    # Save frame as base64
                    _, buffer = cv2.imencode('.jpg', frame)
                    image_base64 = base64.b64encode(buffer).decode('utf-8')
                    
                    try:
                        completion = self.client.chat.completions.create(
                            model="qwen-vl-plus",
                            messages=[{
                                "role": "user",
                                "content": [
                                    {"type": "text", "text": """你是一个严格的安全监控系统。请先分析图像并描述你看到了什么，然后根据规则决定是否需要生成工具调用。

规则1：正常姿势定义
只有两种允许的姿势：
1. 完全站立（双脚站立，身体挺直）
2. 正确坐在椅子上（必须是椅子，沙发，凳子等坐具，不包括地面，台阶等）

规则2：判断流程
1. 先描述你在图像中看到了什么（必须先确认是否有人在画面中）
2. 如果画面中有人且不是上述两种正常姿势之一，生成工具调用：
   {
     "name": "make_emergency_call",
     "arguments": {
       "message": "检测到异常姿势：[具体描述]"
     }
   }

规则3：必须生成工具调用的情况
只有当画面中有人且出现以下任一情况时才生成工具调用：
- 身体任何部位接触地面
- 蹲、跪、趴、躺等任何降低重心的姿势
- 倚靠墙壁或家具
- 弯腰
- 看不清或看不见人物
- 任何不符合正常姿势标准的情况

规则4：禁止事项
- 必须先确认画面中是否有人"""},
                                    {"type": "image_url", "image_url": {
                                        "url": f"data:image/jpeg;base64,{image_base64}"
                                    }}
                                ]
                            }],
                            tools=self.tools,
                            tool_choice="auto"
                        )
                        
                        response_message = completion.choices[0].message
                        
                        print("\n分析结果:", response_message.content)
                        
                        # 首先检查是否有直接的tool_calls
                        if hasattr(response_message, 'tool_calls') and response_message.tool_calls:
                            for tool_call in response_message.tool_calls:
                                if tool_call.function.name == "make_emergency_call":
                                    args = json.loads(tool_call.function.arguments)
                                    print("\n从响应内容中检测到工具调用:")
                                    print("工具调用内容:", tool_call.function.arguments)
                                    make_emergency_call(args["message"], self.emergency_callback)
                        else:
                            # 尝试从文本内容中解析JSON
                            try:
                                content = response_message.content
                                # 查找JSON代码块
                                if "```json" in content:
                                    json_str = content.split("```json")[1].split("```")[0].strip()
                                else:
                                    # 查找大括号之间的内容
                                    start = content.find("{")
                                    end = content.rfind("}") + 1
                                    if start != -1 and end > start:
                                        json_str = content[start:end]
                                    else:
                                        json_str = None
                                
                                if json_str:
                                    tool_call = json.loads(json_str)
                                    if tool_call.get("name") == "make_emergency_call":
                                        args = tool_call.get("arguments", {})
                                        print("\n从文本内容中检测到工具调用:")
                                        print("工具调用内容:", json.dumps(args))
                                        make_emergency_call(args.get("message"), self.emergency_callback)
                            except json.JSONDecodeError as e:
                                print(f"JSON解析错误: {str(e)}")
                            except Exception as e:
                                print(f"处理响应内容时出错: {str(e)}")
                        
                    except Exception as e:
                        print(f"API调用错误: {str(e)}")
                        time.sleep(1)
                        
                except Exception as e:
                    print(f"处理帧时出错: {str(e)}")
                    time.sleep(1)
                    
        except Exception as e:
            print(f"摄像头错误: {str(e)}")
        finally:
            if self.camera:
                self.camera.release()

    def stop(self):
        self.running = False
        if self.camera:
            self.camera.release()
        if os.path.exists("current_frame.jpg"):
            os.remove("current_frame.jpg")

def main():
    detector = CameraDetector()
    try:
        detector.capture_and_analyze()
    except KeyboardInterrupt:
        print("\n正在停止程序...")
    finally:
        detector.stop()

if __name__ == "__main__":
    main()